#pragma once

#include <QVector>
#include <QProgressBar>
#include <QWidget>
#include <vector>
#include "../data/atom.h"
#include "../data/reg3dvolumedata.h"
#include "../data/geometrydata.h"

namespace PBVP {
	/// A class to construct volume data for the skin region of a molecule
	class MolSkin {
	public:
		///
		MolSkin(QWidget* parent = 0);

		/// 
		~MolSkin() {
		}

		/// 
		void getDimension(unsigned int dim[3]) const {
			dim[0] = m_Dim[0];
			dim[1] = m_Dim[1];
			dim[2] = m_Dim[2];
		}
		/// 
		void setDimension(unsigned int dim[3]) {
			m_Dim[0] = dim[0];
			m_Dim[1] = dim[1];
			m_Dim[2] = dim[2];
		}
		///
		Reg3DVolumeData* constructSkinVolume(const QVector<Atom>& atoms);

		/// 
		GeometryData* constructMolSurface(const QVector<Atom>& atoms);

		///
		void setProgressBar(QProgressBar *bar) {
			progressBar = bar;
		}

	private:
		double m_ProbeRadius;
		unsigned int m_Dim[3];
		double m_MinExt[3], m_MaxExt[3];
		double m_Orig[3], m_Span[3];

		unsigned int m_NumVerts, m_NumCells;
		unsigned int m_NumSmallCells, m_NumSmallVerts;
		int m_NumBoundaryCells;
		int m_Depth;
		
		bool* m_SasInteriorVertices;
		bool* m_SasBoundaryVertices;
		bool* m_VDWInteriorVertices;
		bool* m_VDWBoundaryVertices;
		bool* m_SasBoundaryCells;
		unsigned char *m_Regions;

		int* m_IndexOfBoundaryCell;
		std::vector<int> *m_SphereIndices;
		bool* m_SubdividedNodeSasInteriorVertex;
		bool* m_SubdividedNodeSasBoundaryCell;

		QProgressBar *progressBar;

		void setProgress(int prog);

		bool isBoundaryCell(int i, int j, int k, bool *interior);
		bool isBoundaryCell(bool *interior);
		double getDist( double x1, double y1, double z1, double x2, double y2, double z2 );
		void getSolventInterior(const QVector<Atom>& atoms); 
		void getBoundaryCells();
		void computeMinMaxExt(const QVector<Atom>& atoms);
		// get indices of vertices of cell (i, j, k)
		void getCellVerts(int i, int j, int k, int vertId[8], unsigned int dim[3]);
		/// 
		double getDistToSas(int vx, int vy, int vz, int cx, int cy, int cz);
		/// 
		void getBoundarySphereIndices(const QVector<Atom>& atoms);
		/// 
		bool sphereCellIntersect( const Vector3& center, double radius, int ix, int iy, int iz );
		/// 
		void getSubdividedNodesSasInteriorVertices(const QVector<Atom>& atoms);
		/// 
		void getSubdividedNodesSasBoundaryCells();

		static const unsigned char EXTERIOR_VOLUME;
		static const unsigned char SAS_SURFACE;
		static const unsigned char SAS_VOLUME;
		static const unsigned char SES_SURFACE;
		static const unsigned char SES_VOLUME;
		static const unsigned char VDW_SURFACE;
		static const unsigned char VDW_VOLUME;
	};
}